package com.nageoffer.jobtrain.projects.toolkit;

import com.nageoffer.jobtrain.common.web.exception.ClientException;
import com.nageoffer.jobtrain.projects.common.enums.ContestRemindTypeEnums;
import com.nageoffer.jobtrain.projects.dto.resp.ContestRemindQueryRespDTO;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import static com.nageoffer.jobtrain.projects.common.enums.ContestRemindTypeEnums.APP;

/**
 * 用户预约竞赛工具类 -根据预约时间和预约类型计算 bitMap
 * author：唐晨
 */
public class ContestRemindUtils {
    /**
     * 每种预约类型所占用的bits，即6位，每10分钟一个位数（总计每种类型大致能预约 60分钟）
     * 也代表下一个类型的位移量
     */
    private static final int NEXT_TYPE_BITS = 6;

    /**
     * 每个预约通知类型，10分钟为一个间隔
     */
    private static final int TIME_INTERVAL = 10;

    /**
     * 竞赛预约通知方式类型数量
     */
    private static final int TYPE_COUNT = ContestRemindTypeEnums.values().length;

    /**
     * 根据预约时间和预约类型计算出 bitMap
     */
    public static Long calculateBitMap(Integer remindTime, Integer type) {
        if (remindTime > NEXT_TYPE_BITS * TIME_INTERVAL) {
            throw new ClientException("用户预约竞赛开始通知的时间不能早于竞赛开始前 " + NEXT_TYPE_BITS * TIME_INTERVAL + "分钟");
        }
        /**
         * 比如：预约60分钟的APP站内通知
         * 1 << (0 * 6 + Math.max(0, 60 / 5 - 1 = 11))
         */
        return 1L << (type * NEXT_TYPE_BITS + Math.max(0, remindTime / TIME_INTERVAL - 1));
    }

    /**
     * 根据竞赛预约提醒信息，进行解析预约通知时间以及类型
     */
    public static void fillRemindInformationBitMap(ContestRemindQueryRespDTO requestParam, Long information) {
        List<Integer> remindAPPTime = new ArrayList<>();
        List<Integer> remindSMSTime = new ArrayList<>();
        for (int i = NEXT_TYPE_BITS - 1; i >= 0; i--) {
            for (int j = 0; j < TYPE_COUNT; j++) {
                // 右移动，判断是否有预约点，如果 & 1 == 1 就说明有预约点
                if (((information >> (j * NEXT_TYPE_BITS + i)) & 1) == 1) {
                    if (ContestRemindTypeEnums.getByType(j) == APP) {
                        remindAPPTime.add((i + 1) * TIME_INTERVAL);
                    } else {
                        remindSMSTime.add((i + 1) * TIME_INTERVAL);
                    }
                }
            }
        }
        // 将预约时间从小到大排序
        Collections.sort(remindAPPTime);
        Collections.sort(remindSMSTime);

        requestParam.setRemindAPPTime(remindAPPTime);
        requestParam.setRemindSMSTime(remindSMSTime);
    }
}
